package com.jjrwa.action;

import com.intellij.openapi.actionSystem.AnActionEvent;
import com.intellij.openapi.command.WriteCommandAction;
import com.intellij.openapi.project.Project;
import com.intellij.openapi.ui.Messages;
import com.intellij.psi.*;
import com.intellij.psi.impl.source.PsiClassReferenceType;
import com.jjrwa.component.EntityTransformTable;
import com.jjrwa.component.TableDataHandle;
import com.jjrwa.define.HandleClass;
import com.jjrwa.define.HandleClassField;
import com.jjrwa.from.BuildClassTable;
import com.jjrwa.from.UIFieldTable;
import com.jjrwa.transform.IButtonEvent;
import com.jjrwa.transform.IClassTable;
import com.jjrwa.utils.FileHandleUtils;

import javax.swing.*;
import java.awt.event.MouseEvent;
import java.util.ArrayList;
import java.util.List;

public class MapperToXml extends JavaFileAction {

    @Override
    public void actionPerformed(AnActionEvent e) {
        try {
            generateXmlForMapper(e);
        } catch (Exception exception) {
            Messages.showErrorDialog(exception.getMessage(), "File Transform Error");
        }
    }

    @Override
    protected String judgeAnnotation() {
        return "org.apache.ibatis.annotations.Mapper";
    }


    private PsiClass extractEntityClassFromMapper(PsiClass mapperClass) {
        final String BASE_MAPPER_PREFIX = "com.zh.fsc.provide.basics.mybatis.base.IBaseMapper";

        for (PsiClassType type : mapperClass.getExtendsListTypes()) {
            String typeText = type.getCanonicalText();
            if (typeText != null && typeText.startsWith(BASE_MAPPER_PREFIX + "<")) {
                // 安全获取泛型参数
                PsiType[] parameters = type instanceof PsiClassReferenceType ?
                        ((PsiClassReferenceType)type).getParameters() : PsiType.EMPTY_ARRAY;

                if (parameters.length > 0 && parameters[0] instanceof PsiClassType) {
                    return ((PsiClassType)parameters[0]).resolve();
                }
            }
        }
        return null;
    }
//    private PsiClass getSelectedPsiClass(AnActionEvent e) {
//        PsiElement element = e.getData(PlatformDataKeys.PSI_ELEMENT);
//        return element instanceof PsiClass ? (PsiClass) element : null;
//    }
    private void generateXmlForMapper(AnActionEvent event) {
        PsiJavaFile javaFile = FileHandleUtils.getPsiJavaFile(event);
        if (javaFile == null) {
            return;
        }
        //实体类紧紧包含一个class文件
        PsiClass mapperClass = javaFile.getClasses()[0];
        if (mapperClass == null) {
            Messages.showErrorDialog("没找到Mapper接口类", "生成错误");
        }
        // 1. 获取Mapper的泛型参数类型（实体类）
        PsiClass entityClass = extractEntityClassFromMapper(mapperClass);
        if (entityClass == null) {
            Messages.showErrorDialog("无法确定Mapper的实体类型", "生成错误");
            return;
        }
        //className
        String className = mapperClass.getName();
        String qualifiedName = mapperClass.getQualifiedName();
        //自定义处理
        HandleClass handleClass = new HandleClass();
        handleClass.setClassName(className);
        handleClass.setOldClassName(qualifiedName);
        handleClass.setEntityClassName(entityClass.getQualifiedName());

        //字段处理
        List<HandleClassField> fields = new ArrayList<>();
        PsiField[] allFields = entityClass.getFields();
        for (PsiField psiField : allFields) {
            PsiAnnotation propertyAnn = psiField.getAnnotation("io.swagger.annotations.ApiModelProperty");
            if (propertyAnn == null) {
                continue;
            }
            PsiAnnotation transientAnn = psiField.getAnnotation("javax.persistence.Transient");
            if (transientAnn != null) {
                continue;
            }
            PsiType type = psiField.getType();
            //加入字段中
            fields.add(new HandleClassField(psiField.getName(), camelToUnderline(psiField.getName()), type.getPresentableText()));
        }
        handleClass.setFields(fields);

        PsiAnnotation apiModelAnn = entityClass.getAnnotation("io.swagger.annotations.ApiModel");
        if (apiModelAnn == null) {
            Messages.showErrorDialog("实体类未配置@apiModel", "生成错误");
        }
        PsiAnnotationMemberValue memberValue = apiModelAnn.findAttributeValue("description");
        if (null == memberValue) {
            Messages.showErrorDialog("实体类配置的@apiModel注解中，未给description字段赋值", "生成错误");
        }
        //实体描述
        String classDescription = memberValue.getText().replace("\"", "");

        //表格通用处理
        IClassTable iClassTable = new IClassTable() {
            @Override
            public String getTitle() {
                return "Create " + className
                        + ".xml";
            }
            @Override
            public String getClassName() {
                return handleClass.getClassName();
            }
            @Override
            public String getClassDescription() {
                return classDescription+"XML生成";
            }
        };

        //成功处理
        IButtonEvent okButtonEvent = new IButtonEvent() {
            @Override
            public boolean handle(MouseEvent e, JFrame jFrame, JTextField classNameText, JTextField descriptionText) {
                handleClass.setClassName(classNameText.getText());
                handleClass.setDescription(descriptionText.getText());

                Project project = mapperClass.getProject(); // 从类成员变量或事件中获取Project
                PsiDirectory containingDirectory = javaFile.getContainingDirectory();
                PsiDirectory parentDirectory = containingDirectory.getParentDirectory();

                // 使用写操作
                WriteCommandAction.runWriteCommandAction(project, () -> {
                    PsiDirectory childDirectory = parentDirectory.findSubdirectory("xml");
                    if (childDirectory == null) {
                        childDirectory = parentDirectory.createSubdirectory("xml"); // 现在安全了
                    } else {
                        boolean exists = FileHandleUtils.checkClassName(childDirectory, handleClass.getClassName());
                        if (!exists) {
                            return;
                        }
                    }
                    FileHandleUtils.createXmlFile(event, "mapper.ftl", handleClass, childDirectory,handleClass.getClassName());
                });
                return true;
            }
        };

        IButtonEvent fieldsButtonEvent = new IButtonEvent() {
            @Override
            public void handle(MouseEvent e) {
                    new UIFieldTable(new TableDataHandle<>(
                            HandleClassField.class, handleClass.getFields()), h -> new EntityTransformTable(h));
            }

        };
        new BuildClassTable(iClassTable, okButtonEvent, fieldsButtonEvent);
    }


    public String camelToUnderline(String camelCase) {
        if (camelCase == null || camelCase.isEmpty()) {
            return camelCase;
        }
        StringBuilder result = new StringBuilder();
        for (int i = 0; i < camelCase.length(); i++) {
            char ch = camelCase.charAt(i);
            if (Character.isUpperCase(ch)) {
                result.append('_').append(Character.toLowerCase(ch));
            } else {
                result.append(ch);
            }
        }
        return result.toString();
    }

}
